package com.cls.system.controller;

import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.cls.business.entity.Report;
import com.cls.business.entity.Review;
import com.cls.business.service.IReportService;
import com.cls.business.service.IReviewService;
import com.cls.common.annotation.ControllerEndpoint;
import com.cls.common.controller.BaseController;
import com.cls.common.entity.MyConstant;
import com.cls.common.entity.QueryRequest;
import com.cls.common.entity.ResponseVO;
import com.cls.common.enums.DictEnum;
import com.cls.common.utils.MyUtil;
import com.cls.system.entity.Expert;
import com.cls.system.entity.ExpertUserVO;
import com.cls.system.entity.SysDict;
import com.cls.system.entity.User;
import com.cls.system.service.IExpertService;
import com.cls.system.service.ISysDictService;
import com.cls.system.service.IUserService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;

/**
 * 专家表 Controller
 *
 * @author Carey
 * @date 2020-11-06 10:47:30
 */
@Slf4j
@Validated
@Controller
@RequiredArgsConstructor
public class ExpertController extends BaseController {

    private final IExpertService expertService;
    private final ISysDictService sysDictService;
    private final IUserService userService;
    private final IReportService reportService;
    private final IReviewService reviewService;

    @GetMapping(MyConstant.VIEW_PREFIX + "expert")
    public String expertIndex(){
        return MyUtil.view("expert/expert");
    }


    @GetMapping("expert/list")
    @ResponseBody
    @RequiresPermissions("expert:list")
    public ResponseVO expertList(QueryRequest request, Expert expert) {
        PageInfo<Expert> pageInfo =  this.expertService.findExperts(request, expert);
        return ResponseVO.success(pageInfo);
    }

    @ControllerEndpoint(operation = "新增Expert", exceptionMessage = "新增Expert失败")
    @PostMapping("expert")
    @ResponseBody
    @RequiresPermissions("expert:add")
    public ResponseVO addExpert(@Valid Expert expert) {
        expert.setIsPublish(false);
        Integer mobileNum=this.expertService.findByMobile(expert.getMobile());
        Integer idCardNum=this.expertService.findByIdCard(expert.getIdentityId());
        if(mobileNum>0){
            return ResponseVO.failure("新增失败！当前手机号已存在");
        }
        if(idCardNum>0){
            return ResponseVO.failure("新增失败！当前身份证已存在");
        }
        this.expertService.createExpert(expert);

        return ResponseVO.success();
    }
    @ControllerEndpoint(operation = "发布专家多选", exceptionMessage = "发布专家失败")
    @PostMapping("expert/pubishAll/{expertIds}")
    @ResponseBody
    @RequiresPermissions("expert:update")
    public ResponseVO pubishAllExpert(@NotBlank(message = "{required}") @PathVariable String expertIds) {
        String[] ids = expertIds.split(StringPool.COMMA);

        this.expertService.pubishExperts(ids);
        return ResponseVO.success();
    }


    @ControllerEndpoint(operation = "删除专家", exceptionMessage = "删除专家失败")
    @GetMapping("expert/delete/{expertIds}")
    @ResponseBody
    @RequiresPermissions("expert:delete")
    public ResponseVO deleteExpert(@NotBlank(message = "{required}") @PathVariable String expertIds) {
        String[] ids = expertIds.split(StringPool.COMMA);
        List<String> list = Arrays.asList(ids);
        // 查询当前用户是否存在举报和评审记录
        for (String item:list) {
            Long expertId = Long.valueOf(item);
            //举报记录
            Report report=new Report();
            report.setExpertId(expertId);
            int reportSize = reportService.findReports(report).size();
            if(reportSize>0){
                return ResponseVO.failure("不能删除，该专家存在举报信息");
            }
            //评审记录
            Review review=new Review();
            review.setExpertId(expertId);
            int reviewSize = reviewService.findReviews(review).size();
            if(reviewSize>0){
                return ResponseVO.failure("不能删除，该专家存在评审信息");
            }
        }
        this.expertService.deleteExperts(ids);
        return ResponseVO.success();
    }
    @ControllerEndpoint(operation = "发布专家", exceptionMessage = "发布专家失败")
    @PostMapping("expert/pubish/{expertId}")
    @ResponseBody
    @RequiresPermissions("expert:update")
    public ResponseVO pubishExpert(@PathVariable Long expertId,Boolean isPublish) {
        Expert expert=new Expert();
        expert.setExpertId(expertId);
        expert.setIsPublish(isPublish);
        this.expertService.updateExpert(expert);
        return ResponseVO.success();
    }

   /* @ControllerEndpoint(operation = "取消发布专家", exceptionMessage = "取消发布失败")
    @GetMapping("expert/cancel/{expertIds}")
    @ResponseBody
    @RequiresPermissions("expert:update")
    public ResponseVO cancelExpert(@NotBlank(message = "{required}") @PathVariable String expertIds) {
        String[] ids = expertIds.split(StringPool.COMMA);
        this.expertService.cancelExperts(ids);
        return ResponseVO.success();
    }*/
   @ControllerEndpoint(operation = "分配专家用户", exceptionMessage = "分配失败")
   @PostMapping("expert/user")
   @ResponseBody
   @RequiresPermissions("expert:update")
   public ResponseVO updateExpertUser(ExpertUserVO expertUserVO) {
       //查询用户表账号是否存在相同
       User user = userService.findByName(expertUserVO.getUserName());
      if(user!=null){
          return ResponseVO.failure("已存在专家账号！请修改");
      }
       //给专家分配账号
       Expert expert = expertService.getById(expertUserVO.getExpertId());

      userService.expertUser(expert,expertUserVO);
       return ResponseVO.success();
   }


    @ControllerEndpoint(operation = "修改专家", exceptionMessage = "修改专家失败")
    @PostMapping("expert/update")
    @ResponseBody
//    @RequiresPermissions("expert:update")
    public ResponseVO updateExpert(Expert expert) {
        Expert expertByMobile =new Expert();
        expertByMobile.setMobile(expert.getMobile());
        List<Expert> expertList = this.expertService.findExperts(expertByMobile);
        for (Expert e:expertList) {
            if(expert.getMobile().equals(e.getMobile())&&!(expert.getExpertId().equals(e.getExpertId()))){
                return ResponseVO.failure("修改失败！当前手机号已存在.");
            }
        }
        Expert expertIdCard =new Expert();
        expertByMobile.setIdentityId(expert.getIdentityId());
        List<Expert> expertIdCardList = this.expertService.findExperts(expertIdCard);
        for (Expert e:expertIdCardList) {
            if(expert.getIdentityId().equals(e.getIdentityId())&&!(expert.getExpertId().equals(e.getExpertId()))){
                return ResponseVO.failure("修改失败！当前身份证号已存在.");
            }
        }
        this.expertService.updateExpert(expert);
        return ResponseVO.success();
    }

    @ControllerEndpoint(operation = "导出专家", exceptionMessage = "导出专家失败")
    @GetMapping("expert/export")
    @ResponseBody
    @RequiresPermissions("expert:export")
    public void export(Expert expert, HttpServletResponse response) throws IOException {
        List<Expert> experts = this.expertService.findExperts(expert);
        //Hutool 工具库导出Excel表格
        this.expertService.download(experts, response);
    }

    @ControllerEndpoint(operation = "导入专家", exceptionMessage = "导入失败")
    @PostMapping("expert/import")
    @ResponseBody
    @RequiresPermissions("expert:import")
    public ResponseVO importExpert(@RequestParam MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if ("".equals(fileName)) {
            System.out.println("未选择导入的EXCEL文件");
            throw new IOException();
        }
        if (!file.isEmpty()) {
            // 1.获取上传文件输入流
            InputStream inputStream = file.getInputStream();
            this.expertService.uploadExpert(inputStream);
        }
        System.out.println("新增成功");
        return ResponseVO.success();
    }
    @ControllerEndpoint(operation = "模板下载", exceptionMessage = "模板下载")
    @ApiOperation("模板下载")
    @GetMapping(value = "expert/downloadT")
    public void downloadT(HttpServletResponse response) {
        InputStream is = null;
        try {
            ClassPathResource cpr = new ClassPathResource("/templates/export/Expert.xlsx");
            is = cpr.getInputStream();
            Workbook workbook = new XSSFWorkbook(is);
            String fileName = "专家导入模板.xlsx";
            downLoadExcel(fileName, response, workbook);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            IoUtil.close(is);
        }
    }


    @GetMapping(MyConstant.VIEW_PREFIX + "system/expert/detail/{expertId}")
    @RequiresPermissions("expert:list")
    public String systemExpertDetail(@PathVariable Long expertId, Model model) {
        resolveExpertModel(expertId, model, true);
        return MyUtil.view("system/expert/expertDetail");
    }

    @GetMapping(MyConstant.VIEW_PREFIX + "system/expert/update/{expertId}")
//    @RequiresPermissions("expert:update")
    public String systemExpertUpdate(@PathVariable Long expertId, Model model) {
        resolveExpertModel(expertId, model, false);
        //进入修改页面字典表初始化
        //学科分类
        List<SysDict> subjectTypeList = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectTypeList",subjectTypeList);
        //行政职务
       /* List<SysDict> positionList = sysDictService.findByParentCode(DictEnum.POSITION.getCode());
        model.addAttribute("positionList",positionList);*/
        //职称
        /*List<SysDict> titleList = sysDictService.findByParentCode(DictEnum.TITLE.getCode());
        model.addAttribute("titleList",titleList);*/
        //学位
        /*List<SysDict> degreeList = sysDictService.findByParentCode(DictEnum.DEGREE.getCode());
        model.addAttribute("degreeList",degreeList);*/
        //理论与实务专家
        List<SysDict> featureList = sysDictService.findByParentCode(DictEnum.FEATURE.getCode());
        model.addAttribute("featureList",featureList);
        //京内与京外专家
        List<SysDict> districtList = sysDictService.findByParentCode(DictEnum.DISTRICT.getCode());
        model.addAttribute("districtList",districtList);
        //证件类型
        List<SysDict> zjlxList = sysDictService.findByParentCode(DictEnum.ZJLX.getCode());
        model.addAttribute("zjlxList",zjlxList);

        return MyUtil.view("system/expert/expertUpdate");
    }

    @GetMapping(MyConstant.VIEW_PREFIX + "system/expert/user/{expertId}")
    @RequiresPermissions("expert:update")
    public String expertAddUser(@PathVariable Long expertId, Model model) {
        model.addAttribute("expertId",expertId);
        return MyUtil.view("system/expert/expertUser");
    }

    @GetMapping(MyConstant.VIEW_PREFIX + "system/expert")
    @RequiresPermissions("expert:list")
    public String systemExpert(Model model) {
        //进入修改页面字典表初始化
        //学科分类
        List<SysDict> subjectTypeList = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectTypeList",subjectTypeList);
        //京内/京外专家
        List<SysDict> districtList = sysDictService.findByParentCode(DictEnum.DISTRICT.getCode());
        model.addAttribute("districtList",districtList);
        //理论/实务专家
        List<SysDict> featureList = sysDictService.findByParentCode(DictEnum.FEATURE.getCode());
        model.addAttribute("featureList",featureList);

        return MyUtil.view("system/expert/expert");
    }

    @GetMapping(MyConstant.VIEW_PREFIX + "system/expert/add")
    @RequiresPermissions("expert:add")
    public String systemExpertAdd(Model model) {
        //进入新增页面字典表初始化
        //学科分类
        List<SysDict> subjectTypeList = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectTypeList",subjectTypeList);
        //理论与实务专家
        List<SysDict> featureList = sysDictService.findByParentCode(DictEnum.FEATURE.getCode());
        model.addAttribute("featureList",featureList);
        //京内与京外专家
        List<SysDict> districtList = sysDictService.findByParentCode(DictEnum.DISTRICT.getCode());
        model.addAttribute("districtList",districtList);

        //证件类型
        List<SysDict> zjlxList = sysDictService.findByParentCode(DictEnum.ZJLX.getCode());
        model.addAttribute("zjlxList",zjlxList);

        return MyUtil.view("system/expert/expertAdd");
    }

    private void resolveExpertModel(Long expertId, Model model, Boolean transform) {
        Expert expert = expertService.findById(expertId);
        if(expert.getIsPublish()){
            expert.setIsPublishName("是");
        }else {
            expert.setIsPublishName("否");
        }
        model.addAttribute("expert", expert);

    }
    public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
        ServletOutputStream outputStream = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //此处记得关闭输出Servlet流
            IoUtil.close(outputStream);
        }
    }

}
